package com.tengju.settlement.domain.model.depository;

import com.tengju.settlement.domain.model.account.UserIdCode;
import com.tengju.settlement.domain.shared.DomainException;
import com.tengju.settlement.domain.shared.DomainExceptionCode;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.experimental.NonFinal;

import java.time.Duration;
import java.time.LocalDateTime;

@Value
@AllArgsConstructor
public class DepositoryBankCard {

    @NonFinal
    DepositoryBankCardId depositoryBankCardId;

    @NonFinal
    UserIdCode idCode;

    @NonFinal
    DepositoryAccountId depositoryAccountId;

    @NonFinal
    BankCardType cardType;

    @NonFinal
    String cardNo;

    @NonFinal
    String bankName;

    @NonFinal
    String superBankNo;

    @NonFinal
    BindStatus status;


    @NonFinal
    BankCardExtra extra;

    public Long remainSecond() {
        Duration between = Duration.between(LocalDateTime.now(), extra.verifyExpireTime);
        return between.getSeconds() > 0 ? between.getSeconds() : 0;
    }

    public static void main(String[] args) {
        Duration between = Duration.between( LocalDateTime.now(),LocalDateTime.now().minusSeconds(35));
        System.out.println(between.getSeconds());
    }

    public void retryBind(String bankName,String superBankNo,String reservedMobile) {
        this.bankName = bankName;
        this.superBankNo = superBankNo;
        if (cardType == BankCardType.PUBLIC) {
            extra.setRetryNum(0);
            extra.setVerifyExpireTime(LocalDateTime.now().plusDays(2));
            changeBindStatus(BindStatus.AUTHENTICATING);
        } else {
            extra.setVerifyExpireTime(LocalDateTime.now().plusMinutes(2));
            extra.setReservedMobile(reservedMobile);
        }
    }

    public void sync(UserIdCode idCode,DepositoryAccountId depositoryAccountId) {
        this.idCode = idCode;
        this.depositoryAccountId = depositoryAccountId;
        this.status = BindStatus.SUCCESS;
    }


    public void changeBindStatus(BindStatus afterStatus) {

        if (BindStatus.SUCCESS == afterStatus && (BindStatus.AUTHENTICATING == this.status ||BindStatus.INIT == this.status ||
                BindStatus.FAIL == this.status || BindStatus.LOGICAL_UNBIND == this.status)) {
            this.status = BindStatus.SUCCESS;
        } else if (BindStatus.AUTHENTICATING == afterStatus && BindStatus.FAIL == this.status) {
            this.status = BindStatus.AUTHENTICATING;
        } else if (BindStatus.FAIL == afterStatus && (BindStatus.AUTHENTICATING == this.status)) {
            this.status = BindStatus.FAIL;
        } else if (BindStatus.LOGICAL_UNBIND == afterStatus && (BindStatus.SUCCESS == this.status)) {
            this.status = BindStatus.LOGICAL_UNBIND;
        } else {
            throw DomainException.error(DomainExceptionCode.DEP_BANK_CARD_BIND_STATUS_CHANGE_FAIL);
        }

    }


    public DepositoryBankCard(String bankName, String cardNo, BankCardType bankCardType, String superBankNo, String mobile){
        this.bankName = bankName;
        this.cardNo = cardNo;
        this.cardType = bankCardType;
        this.superBankNo = superBankNo;
        if (extra != null) {
            extra.setReservedMobile(mobile);
        } else {
            BankCardExtra bankCardExtra = new BankCardExtra();
            bankCardExtra.setReservedMobile(mobile);
            this.extra = bankCardExtra;
        }
    }

    public DepositoryBankCard(String bankName, String superBankNo, String cardNo){
        this.bankName = bankName;
        this.superBankNo = superBankNo;
        this.cardNo = cardNo;
    }


    public String last4CardNo() {
        String accountName;
        if (bankName.length() <= 13) {
            accountName = bankName + "(" + cardNo.substring(cardNo.length() - 4) + ")";
        } else {
            accountName = bankName.substring(0,13) + "..." + "(" + cardNo.substring(cardNo.length() - 4) + ")";
        }
        return accountName;
    }



    public boolean equalsCardNo(String cardNo) {
        return this.cardNo.equals(cardNo);
    }

    public boolean isLogicalUnbind() {
        return BindStatus.LOGICAL_UNBIND == status;
    }

    public boolean isFailed() {
        return BindStatus.FAIL == status;
    }

    public void bindSuccess() {
        changeBindStatus(BindStatus.SUCCESS);
    }

    public void logicalUnbind() {
        changeBindStatus(BindStatus.LOGICAL_UNBIND);
    }

}
